home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / lib / python2.6 / bdb.py < prev    next >
Text File  |  2009-11-02  |  20KB  |  614 lines

  1. """Debugger basics"""
  2.  
  3. import sys
  4. import os
  5. import types
  6.  
  7. __all__ = ["BdbQuit","Bdb","Breakpoint"]
  8.  
  9. class BdbQuit(Exception):
  10.     """Exception to give up completely"""
  11.  
  12.  
  13. class Bdb:
  14.  
  15.     """Generic Python debugger base class.
  16.  
  17.     This class takes care of details of the trace facility;
  18.     a derived class should implement user interaction.
  19.     The standard debugger class (pdb.Pdb) is an example.
  20.     """
  21.  
  22.     def __init__(self):
  23.         self.breaks = {}
  24.         self.fncache = {}
  25.  
  26.     def canonic(self, filename):
  27.         if filename == "<" + filename[1:-1] + ">":
  28.             return filename
  29.         canonic = self.fncache.get(filename)
  30.         if not canonic:
  31.             canonic = os.path.abspath(filename)
  32.             canonic = os.path.normcase(canonic)
  33.             self.fncache[filename] = canonic
  34.         return canonic
  35.  
  36.     def reset(self):
  37.         import linecache
  38.         linecache.checkcache()
  39.         self.botframe = None
  40.         self._set_stopinfo(None, None)
  41.  
  42.     def trace_dispatch(self, frame, event, arg):
  43.         if self.quitting:
  44.             return # None
  45.         if event == 'line':
  46.             return self.dispatch_line(frame)
  47.         if event == 'call':
  48.             return self.dispatch_call(frame, arg)
  49.         if event == 'return':
  50.             return self.dispatch_return(frame, arg)
  51.         if event == 'exception':
  52.             return self.dispatch_exception(frame, arg)
  53.         if event == 'c_call':
  54.             return self.trace_dispatch
  55.         if event == 'c_exception':
  56.             return self.trace_dispatch
  57.         if event == 'c_return':
  58.             return self.trace_dispatch
  59.         print 'bdb.Bdb.dispatch: unknown debugging event:', repr(event)
  60.         return self.trace_dispatch
  61.  
  62.     def dispatch_line(self, frame):
  63.         if self.stop_here(frame) or self.break_here(frame):
  64.             self.user_line(frame)
  65.             if self.quitting: raise BdbQuit
  66.         return self.trace_dispatch
  67.  
  68.     def dispatch_call(self, frame, arg):
  69.         # XXX 'arg' is no longer used
  70.         if self.botframe is None:
  71.             # First call of dispatch since reset()
  72.             self.botframe = frame.f_back # (CT) Note that this may also be None!
  73.             return self.trace_dispatch
  74.         if not (self.stop_here(frame) or self.break_anywhere(frame)):
  75.             # No need to trace this function
  76.             return # None
  77.         self.user_call(frame, arg)
  78.         if self.quitting: raise BdbQuit
  79.         return self.trace_dispatch
  80.  
  81.     def dispatch_return(self, frame, arg):
  82.         if self.stop_here(frame) or frame == self.returnframe:
  83.             self.user_return(frame, arg)
  84.             if self.quitting: raise BdbQuit
  85.         return self.trace_dispatch
  86.  
  87.     def dispatch_exception(self, frame, arg):
  88.         if self.stop_here(frame):
  89.             self.user_exception(frame, arg)
  90.             if self.quitting: raise BdbQuit
  91.         return self.trace_dispatch
  92.  
  93.     # Normally derived classes don't override the following
  94.     # methods, but they may if they want to redefine the
  95.     # definition of stopping and breakpoints.
  96.  
  97.     def stop_here(self, frame):
  98.         # (CT) stopframe may now also be None, see dispatch_call.
  99.         # (CT) the former test for None is therefore removed from here.
  100.         if frame is self.stopframe:
  101.             return frame.f_lineno >= self.stoplineno
  102.         while frame is not None and frame is not self.stopframe:
  103.             if frame is self.botframe:
  104.                 return True
  105.             frame = frame.f_back
  106.         return False
  107.  
  108.     def break_here(self, frame):
  109.         filename = self.canonic(frame.f_code.co_filename)
  110.         if not filename in self.breaks:
  111.             return False
  112.         lineno = frame.f_lineno
  113.         if not lineno in self.breaks[filename]:
  114.             # The line itself has no breakpoint, but maybe the line is the
  115.             # first line of a function with breakpoint set by function name.
  116.             lineno = frame.f_code.co_firstlineno
  117.             if not lineno in self.breaks[filename]:
  118.                 return False
  119.  
  120.         # flag says ok to delete temp. bp
  121.         (bp, flag) = effective(filename, lineno, frame)
  122.         if bp:
  123.             self.currentbp = bp.number
  124.             if (flag and bp.temporary):
  125.                 self.do_clear(str(bp.number))
  126.             return True
  127.         else:
  128.             return False
  129.  
  130.     def do_clear(self, arg):
  131.         raise NotImplementedError, "subclass of bdb must implement do_clear()"
  132.  
  133.     def break_anywhere(self, frame):
  134.         return self.canonic(frame.f_code.co_filename) in self.breaks
  135.  
  136.     # Derived classes should override the user_* methods
  137.     # to gain control.
  138.  
  139.     def user_call(self, frame, argument_list):
  140.         """This method is called when there is the remote possibility
  141.         that we ever need to stop in this function."""
  142.         pass
  143.  
  144.     def user_line(self, frame):
  145.         """This method is called when we stop or break at this line."""
  146.         pass
  147.  
  148.     def user_return(self, frame, return_value):
  149.         """This method is called when a return trap is set here."""
  150.         pass
  151.  
  152.     def user_exception(self, frame, exc_info):
  153.         exc_type, exc_value, exc_traceback = exc_info
  154.         """This method is called if an exception occurs,
  155.         but only if we are to stop at or just below this level."""
  156.         pass
  157.  
  158.     def _set_stopinfo(self, stopframe, returnframe, stoplineno=-1):
  159.         self.stopframe = stopframe
  160.         self.returnframe = returnframe
  161.         self.quitting = 0
  162.         self.stoplineno = stoplineno
  163.  
  164.     # Derived classes and clients can call the following methods
  165.     # to affect the stepping state.
  166.  
  167.     def set_until(self, frame): #the name "until" is borrowed from gdb
  168.         """Stop when the line with the line no greater than the current one is
  169.         reached or when returning from current frame"""
  170.         self._set_stopinfo(frame, frame, frame.f_lineno+1)
  171.  
  172.     def set_step(self):
  173.         """Stop after one line of code."""
  174.         self._set_stopinfo(None,None)
  175.  
  176.     def set_next(self, frame):
  177.         """Stop on the next line in or below the given frame."""
  178.         self._set_stopinfo(frame, None)
  179.  
  180.     def set_return(self, frame):
  181.         """Stop when returning from the given frame."""
  182.         self._set_stopinfo(frame.f_back, frame)
  183.  
  184.     def set_trace(self, frame=None):
  185.         """Start debugging from `frame`.
  186.  
  187.         If frame is not specified, debugging starts from caller's frame.
  188.         """
  189.         if frame is None:
  190.             frame = sys._getframe().f_back
  191.         self.reset()
  192.         while frame:
  193.             frame.f_trace = self.trace_dispatch
  194.             self.botframe = frame
  195.             frame = frame.f_back
  196.         self.set_step()
  197.         sys.settrace(self.trace_dispatch)
  198.  
  199.     def set_continue(self):
  200.         # Don't stop except at breakpoints or when finished
  201.         self._set_stopinfo(self.botframe, None)
  202.         if not self.breaks:
  203.             # no breakpoints; run without debugger overhead
  204.             sys.settrace(None)
  205.             frame = sys._getframe().f_back
  206.             while frame and frame is not self.botframe:
  207.                 del frame.f_trace
  208.                 frame = frame.f_back
  209.  
  210.     def set_quit(self):
  211.         self.stopframe = self.botframe
  212.         self.returnframe = None
  213.         self.quitting = 1
  214.         sys.settrace(None)
  215.  
  216.     # Derived classes and clients can call the following methods
  217.     # to manipulate breakpoints.  These methods return an
  218.     # error message is something went wrong, None if all is well.
  219.     # Set_break prints out the breakpoint line and file:lineno.
  220.     # Call self.get_*break*() to see the breakpoints or better
  221.     # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
  222.  
  223.     def set_break(self, filename, lineno, temporary=0, cond = None,
  224.                   funcname=None):
  225.         filename = self.canonic(filename)
  226.         import linecache # Import as late as possible
  227.         line = linecache.getline(filename, lineno)
  228.         if not line:
  229.             return 'Line %s:%d does not exist' % (filename,
  230.                                    lineno)
  231.         if not filename in self.breaks:
  232.             self.breaks[filename] = []
  233.         list = self.breaks[filename]
  234.         if not lineno in list:
  235.             list.append(lineno)
  236.         bp = Breakpoint(filename, lineno, temporary, cond, funcname)
  237.  
  238.     def clear_break(self, filename, lineno):
  239.         filename = self.canonic(filename)
  240.         if not filename in self.breaks:
  241.             return 'There are no breakpoints in %s' % filename
  242.         if lineno not in self.breaks[filename]:
  243.             return 'There is no breakpoint at %s:%d' % (filename,
  244.                                     lineno)
  245.         # If there's only one bp in the list for that file,line
  246.         # pair, then remove the breaks entry
  247.         for bp in Breakpoint.bplist[filename, lineno][:]:
  248.             bp.deleteMe()
  249.         if not Breakpoint.bplist.has_key((filename, lineno)):
  250.             self.breaks[filename].remove(lineno)
  251.         if not self.breaks[filename]:
  252.             del self.breaks[filename]
  253.  
  254.     def clear_bpbynumber(self, arg):
  255.         try:
  256.             number = int(arg)
  257.         except:
  258.             return 'Non-numeric breakpoint number (%s)' % arg
  259.         try:
  260.             bp = Breakpoint.bpbynumber[number]
  261.         except IndexError:
  262.             return 'Breakpoint number (%d) out of range' % number
  263.         if not bp:
  264.             return 'Breakpoint (%d) already deleted' % number
  265.         self.clear_break(bp.file, bp.line)
  266.  
  267.     def clear_all_file_breaks(self, filename):
  268.         filename = self.canonic(filename)
  269.         if not filename in self.breaks:
  270.             return 'There are no breakpoints in %s' % filename
  271.         for line in self.breaks[filename]:
  272.             blist = Breakpoint.bplist[filename, line]
  273.             for bp in blist:
  274.                 bp.deleteMe()
  275.         del self.breaks[filename]
  276.  
  277.     def clear_all_breaks(self):
  278.         if not self.breaks:
  279.             return 'There are no breakpoints'
  280.         for bp in Breakpoint.bpbynumber:
  281.             if bp:
  282.                 bp.deleteMe()
  283.         self.breaks = {}
  284.  
  285.     def get_break(self, filename, lineno):
  286.         filename = self.canonic(filename)
  287.         return filename in self.breaks and \
  288.             lineno in self.breaks[filename]
  289.  
  290.     def get_breaks(self, filename, lineno):
  291.         filename = self.canonic(filename)
  292.         return filename in self.breaks and \
  293.             lineno in self.breaks[filename] and \
  294.             Breakpoint.bplist[filename, lineno] or []
  295.  
  296.     def get_file_breaks(self, filename):
  297.         filename = self.canonic(filename)
  298.         if filename in self.breaks:
  299.             return self.breaks[filename]
  300.         else:
  301.             return []
  302.  
  303.     def get_all_breaks(self):
  304.         return self.breaks
  305.  
  306.     # Derived classes and clients can call the following method
  307.     # to get a data structure representing a stack trace.
  308.  
  309.     def get_stack(self, f, t):
  310.         stack = []
  311.         if t and t.tb_frame is f:
  312.             t = t.tb_next
  313.         while f is not None:
  314.             stack.append((f, f.f_lineno))
  315.             if f is self.botframe:
  316.                 break
  317.             f = f.f_back
  318.         stack.reverse()
  319.         i = max(0, len(stack) - 1)
  320.         while t is not None:
  321.             stack.append((t.tb_frame, t.tb_lineno))
  322.             t = t.tb_next
  323.         if f is None:
  324.             i = max(0, len(stack) - 1)
  325.         return stack, i
  326.  
  327.     #
  328.  
  329.     def format_stack_entry(self, frame_lineno, lprefix=': '):
  330.         import linecache, repr
  331.         frame, lineno = frame_lineno
  332.         filename = self.canonic(frame.f_code.co_filename)
  333.         s = '%s(%r)' % (filename, lineno)
  334.         if frame.f_code.co_name:
  335.             s = s + frame.f_code.co_name
  336.         else:
  337.             s = s + "<lambda>"
  338.         if '__args__' in frame.f_locals:
  339.             args = frame.f_locals['__args__']
  340.         else:
  341.             args = None
  342.         if args:
  343.             s = s + repr.repr(args)
  344.         else:
  345.             s = s + '()'
  346.         if '__return__' in frame.f_locals:
  347.             rv = frame.f_locals['__return__']
  348.             s = s + '->'
  349.             s = s + repr.repr(rv)
  350.         line = linecache.getline(filename, lineno, frame.f_globals)
  351.         if line: s = s + lprefix + line.strip()
  352.         return s
  353.  
  354.     # The following two methods can be called by clients to use
  355.     # a debugger to debug a statement, given as a string.
  356.  
  357.     def run(self, cmd, globals=None, locals=None):
  358.         if globals is None:
  359.             import __main__
  360.             globals = __main__.__dict__
  361.         if locals is None:
  362.             locals = globals
  363.         self.reset()
  364.         sys.settrace(self.trace_dispatch)
  365.         if not isinstance(cmd, types.CodeType):
  366.             cmd = cmd+'\n'
  367.         try:
  368.             exec cmd in globals, locals
  369.         except BdbQuit:
  370.             pass
  371.         finally:
  372.             self.quitting = 1
  373.             sys.settrace(None)
  374.  
  375.     def runeval(self, expr, globals=None, locals=None):
  376.         if globals is None:
  377.             import __main__
  378.             globals = __main__.__dict__
  379.         if locals is None:
  380.             locals = globals
  381.         self.reset()
  382.         sys.settrace(self.trace_dispatch)
  383.         if not isinstance(expr, types.CodeType):
  384.             expr = expr+'\n'
  385.         try:
  386.             return eval(expr, globals, locals)
  387.         except BdbQuit:
  388.             pass
  389.         finally:
  390.             self.quitting = 1
  391.             sys.settrace(None)
  392.  
  393.     def runctx(self, cmd, globals, locals):
  394.         # B/W compatibility
  395.         self.run(cmd, globals, locals)
  396.  
  397.     # This method is more useful to debug a single function call.
  398.  
  399.     def runcall(self, func, *args, **kwds):
  400.         self.reset()
  401.         sys.settrace(self.trace_dispatch)
  402.         res = None
  403.         try:
  404.             res = func(*args, **kwds)
  405.         except BdbQuit:
  406.             pass
  407.         finally:
  408.             self.quitting = 1
  409.             sys.settrace(None)
  410.         return res
  411.  
  412.  
  413. def set_trace():
  414.     Bdb().set_trace()
  415.  
  416.  
  417. class Breakpoint:
  418.  
  419.     """Breakpoint class
  420.  
  421.     Implements temporary breakpoints, ignore counts, disabling and
  422.     (re)-enabling, and conditionals.
  423.  
  424.     Breakpoints are indexed by number through bpbynumber and by
  425.     the file,line tuple using bplist.  The former points to a
  426.     single instance of class Breakpoint.  The latter points to a
  427.     list of such instances since there may be more than one
  428.     breakpoint per line.
  429.  
  430.     """
  431.  
  432.     # XXX Keeping state in the class is a mistake -- this means
  433.     # you cannot have more than one active Bdb instance.
  434.  
  435.     next = 1        # Next bp to be assigned
  436.     bplist = {}     # indexed by (file, lineno) tuple
  437.     bpbynumber = [None] # Each entry is None or an instance of Bpt
  438.                 # index 0 is unused, except for marking an
  439.                 # effective break .... see effective()
  440.  
  441.     def __init__(self, file, line, temporary=0, cond=None, funcname=None):
  442.         self.funcname = funcname
  443.         # Needed if funcname is not None.
  444.         self.func_first_executable_line = None
  445.         self.file = file    # This better be in canonical form!
  446.         self.line = line
  447.         self.temporary = temporary
  448.         self.cond = cond
  449.         self.enabled = 1
  450.         self.ignore = 0
  451.         self.hits = 0
  452.         self.number = Breakpoint.next
  453.         Breakpoint.next = Breakpoint.next + 1
  454.         # Build the two lists
  455.         self.bpbynumber.append(self)
  456.         if self.bplist.has_key((file, line)):
  457.             self.bplist[file, line].append(self)
  458.         else:
  459.             self.bplist[file, line] = [self]
  460.  
  461.  
  462.     def deleteMe(self):
  463.         index = (self.file, self.line)
  464.         self.bpbynumber[self.number] = None   # No longer in list
  465.         self.bplist[index].remove(self)
  466.         if not self.bplist[index]:
  467.             # No more bp for this f:l combo
  468.             del self.bplist[index]
  469.  
  470.     def enable(self):
  471.         self.enabled = 1
  472.  
  473.     def disable(self):
  474.         self.enabled = 0
  475.  
  476.     def bpprint(self, out=None):
  477.         if out is None:
  478.             out = sys.stdout
  479.         if self.temporary:
  480.             disp = 'del  '
  481.         else:
  482.             disp = 'keep '
  483.         if self.enabled:
  484.             disp = disp + 'yes  '
  485.         else:
  486.             disp = disp + 'no   '
  487.         print >>out, '%-4dbreakpoint   %s at %s:%d' % (self.number, disp,
  488.                                                        self.file, self.line)
  489.         if self.cond:
  490.             print >>out, '\tstop only if %s' % (self.cond,)
  491.         if self.ignore:
  492.             print >>out, '\tignore next %d hits' % (self.ignore)
  493.         if (self.hits):
  494.             if (self.hits > 1): ss = 's'
  495.             else: ss = ''
  496.             print >>out, ('\tbreakpoint already hit %d time%s' %
  497.                           (self.hits, ss))
  498.  
  499. # -----------end of Breakpoint class----------
  500.  
  501. def checkfuncname(b, frame):
  502.     """Check whether we should break here because of `b.funcname`."""
  503.     if not b.funcname:
  504.         # Breakpoint was set via line number.
  505.         if b.line != frame.f_lineno:
  506.             # Breakpoint was set at a line with a def statement and the function
  507.             # defined is called: don't break.
  508.             return False
  509.         return True
  510.  
  511.     # Breakpoint set via function name.
  512.  
  513.     if frame.f_code.co_name != b.funcname:
  514.         # It's not a function call, but rather execution of def statement.
  515.         return False
  516.  
  517.     # We are in the right frame.
  518.     if not b.func_first_executable_line:
  519.         # The function is entered for the 1st time.
  520.         b.func_first_executable_line = frame.f_lineno
  521.  
  522.     if  b.func_first_executable_line != frame.f_lineno:
  523.         # But we are not at the first line number: don't break.
  524.         return False
  525.     return True
  526.  
  527. # Determines if there is an effective (active) breakpoint at this
  528. # line of code.  Returns breakpoint number or 0 if none
  529. def effective(file, line, frame):
  530.     """Determine which breakpoint for this file:line is to be acted upon.
  531.  
  532.     Called only if we know there is a bpt at this
  533.     location.  Returns breakpoint that was triggered and a flag
  534.     that indicates if it is ok to delete a temporary bp.
  535.  
  536.     """
  537.     possibles = Breakpoint.bplist[file,line]
  538.     for i in range(0, len(possibles)):
  539.         b = possibles[i]
  540.         if b.enabled == 0:
  541.             continue
  542.         if not checkfuncname(b, frame):
  543.             continue
  544.         # Count every hit when bp is enabled
  545.         b.hits = b.hits + 1
  546.         if not b.cond:
  547.             # If unconditional, and ignoring,
  548.             # go on to next, else break
  549.             if b.ignore > 0:
  550.                 b.ignore = b.ignore -1
  551.                 continue
  552.             else:
  553.                 # breakpoint and marker that's ok
  554.                 # to delete if temporary
  555.                 return (b,1)
  556.         else:
  557.             # Conditional bp.
  558.             # Ignore count applies only to those bpt hits where the
  559.             # condition evaluates to true.
  560.             try:
  561.                 val = eval(b.cond, frame.f_globals,
  562.                        frame.f_locals)
  563.                 if val:
  564.                     if b.ignore > 0:
  565.                         b.ignore = b.ignore -1
  566.                         # continue
  567.                     else:
  568.                         return (b,1)
  569.                 # else:
  570.                 #   continue
  571.             except:
  572.                 # if eval fails, most conservative
  573.                 # thing is to stop on breakpoint
  574.                 # regardless of ignore count.
  575.                 # Don't delete temporary,
  576.                 # as another hint to user.
  577.                 return (b,0)
  578.     return (None, None)
  579.  
  580. # -------------------- testing --------------------
  581.  
  582. class Tdb(Bdb):
  583.     def user_call(self, frame, args):
  584.         name = frame.f_code.co_name
  585.         if not name: name = '???'
  586.         print '+++ call', name, args
  587.     def user_line(self, frame):
  588.         import linecache
  589.         name = frame.f_code.co_name
  590.         if not name: name = '???'
  591.         fn = self.canonic(frame.f_code.co_filename)
  592.         line = linecache.getline(fn, frame.f_lineno, frame.f_globals)
  593.         print '+++', fn, frame.f_lineno, name, ':', line.strip()
  594.     def user_return(self, frame, retval):
  595.         print '+++ return', retval
  596.     def user_exception(self, frame, exc_stuff):
  597.         print '+++ exception', exc_stuff
  598.         self.set_continue()
  599.  
  600. def foo(n):
  601.     print 'foo(', n, ')'
  602.     x = bar(n*10)
  603.     print 'bar returned', x
  604.  
  605. def bar(a):
  606.     print 'bar(', a, ')'
  607.     return a/2
  608.  
  609. def test():
  610.     t = Tdb()
  611.     t.run('import bdb; bdb.foo(10)')
  612.  
  613. # end
  614.